/*
 * Copyright (C) 2010-2011 sunjumper@163.com
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *  http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package mf.mfrpc.http;

import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import mf.mfrpc.serialize.AdapterDataSource;
import mf.mfrpc.serialize.DataSource;
import mf.mfrpc.serialize.DataSourceIterator;
import mf.mfrpc.serialize.Parameter;
import mf.mfrpc.serialize.ParameterType;
import mf.mfrpc.serialize.Parser;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
 * Http传输结构（序列化对象）和非结构（流）数据的解析器。
 */
public class HttpParser {

    /** 流数据参数的起始位置, 规定第一个参数必定是序列化的参数对象 */
    private static final int PARAMETER_DATASOURCE = 2;

    /** 对象序列化解析器 */
    private Parser parser;

    public HttpParser(Parser parser) {
        this.parser = parser;
    }

    /**
     * 解析http请求转换为请求的参数对象。
     *
     * @param request http请求。
     *
     * @return 参数对象。
     * 
     * @throws Exception
     *
     * @see mf.mfrpc.client.RPCHttpClient#invoke(java.lang.Object[]) 
     */
    public Object[] parse(HttpServletRequest request) throws IOException, FileUploadException {
        Parameter param = null;
        // Create a new file upload handler
        ServletFileUpload upload = new ServletFileUpload();

        // Parse the request
        FileItemIterator iter = upload.getItemIterator(request);

        int index = 0;
        out:
        while (index++ < PARAMETER_DATASOURCE && iter.hasNext()) {
            //1st plain parameter
            if (index == 1) {
                FileItemStream first = iter.next();
                if (first.isFormField()) {
                    param = parser.readObject(first.openStream(), Parameter.class);
                } else {
                    throw new IllegalArgumentException("wrong parameter");
                }
            }
            //the remaining stram parameters
            if (index == PARAMETER_DATASOURCE) {
                for (int i = 0; i < param.getParameterTypes().length; i++) {
                    byte type = param.getParameterTypes()[i];
                    if (ParameterType.DATASOURCE == type) {
                        AdapterDataSource ds = new AdapterDataSource((DataSource) param.getParameters()[i]);
                        //2nd single datasource parameter
                        ds.setInputStream(iter.next().openStream());
                        //set the AdapterDataSource to Parameter DataSource
                        param.getParameters()[i] = ds;
                        break out;
                    } else if (ParameterType.DATASOURCES == type) {
                        //the remaining stram parameters
                        param.getParameters()[i] = new HttpDataSourceIterator(iter, (DataSourceIterator) param.getParameters()[i]);
                        break out;
                    }
                }

            }
        }
        //System.out.println(index + "--->" + param);
        return param == null ? null : param.getParameters();
    }

    public static boolean isMultipart(HttpServletRequest request) {
        return ServletFileUpload.isMultipartContent(request);
    }

    public Parser getParser() {
        return parser;
    }
}
